package com.cws.utils;

/**
 * [说明/描述]
 *
 * @author 陈新乐
 * @version 1.0
 * @date 2024/6/27
 */
import cn.hutool.core.lang.Assert;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;

/**
 * desc: FTP工具类
 * Date: 2019/3/27
 * @author gurongkai
 */
@Log4j2
public class FtpUtil {
    private FTPClient ftpClient = null;
    private String hostname;
    private int port;
    private String username;
    private String password;
    private int timeout;

    // 构造方法
    public FtpUtil(String hostname, int port, String username, String password, int timeout) {
        this.hostname = hostname;
        this.port = port;
        this.username = username;
        this.password = password;
        this.timeout = timeout;
    }

    // 登录

    /**
     * FTP登陆
     *
     * @throws IOException
     */
    public void login() throws Exception {
        log.info("登入FTP : hostname : "+hostname+" , port : "+port+ " , timeout : "+timeout);
        ftpClient = new FTPClient();
        ftpClient.configure(getFTPClientConfig());
        ftpClient.setDefaultPort(port);
        ftpClient.setControlEncoding("GBK");
        ftpClient.connect(hostname);
        ftpClient.setConnectTimeout(timeout);
        ftpClient.enterLocalPassiveMode();
        Assert.isTrue(ftpClient.login(username, password),"FTP登陆失败，请检测登陆用户名和密码是否正确!");
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
    }

    /**
     * FTP得到配置
     *
     * @return
     */
    private FTPClientConfig getFTPClientConfig() {
        // 创建配置对象
        FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
        conf.setServerLanguageCode("zh");
        return conf;
    }

    /**
     * FTP关闭FTP服务器
     */
    public void closeServer() {
        try {
            if (ftpClient != null) {
                ftpClient.logout();
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            throw new RuntimeException( e );
        }
    }

    /**
     * FTP链接是否已经打开
     *
     * @return
     */
    public boolean serverIsOpen() {
        if (ftpClient == null) {
            return false;
        }
        return ftpClient.isConnected();
    }

    /**
     * FTP列表FTP文件
     *
     * @param regEx
     * @return
     */
    public String[] listFiles(String regEx) throws IOException {
        String[] names;
        names = ftpClient.listNames(regEx);
        if (names == null) {
            return new String[0];
        }
        return names;
    }

    /**
     * FTP取得FTP操作类的句柄
     *
     * @return
     */
    public FTPClient getFtpClient() {
        return ftpClient;
    }

    /**
     * FTP上传
     *
     * @throws Exception
     */
    public boolean upload(String localFilePath, String remoteFilePath) throws Exception {
        boolean state = false;
        File localFile = new File(localFilePath);
        if (!localFile.isFile() || localFile.length() == 0) {
            return state;
        }
        FileInputStream localIn = new FileInputStream(localFile);
        state = this.upload(localIn, remoteFilePath);
        localIn.close();
        return state;
    }

    /**
     * FTP上传
     *
     * @throws Exception
     */
    public boolean upload(InputStream localIn, String remoteFilePath) throws Exception {
        /* this.createDir(new File(remoteFilePath).getParent()); */
        return ftpClient.storeFile(remoteFilePath, localIn);
    }

    /**
     * FTP是否存在FTP目录
     * @param dir
     * @return
     */
    public boolean isDirExist(String dir) {
        try {
            int retCode = ftpClient.cwd(dir);
            return FTPReply.isPositiveCompletion(retCode);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * FTP创建FTP多级目录
     * @param dir
     * @throws IOException
     */
    public void createDir(String dir) throws IOException {
        if (!isDirExist(dir) && dir != null) {
            File file = new File(dir);
            this.createDir(file.getParent());
            ftpClient.makeDirectory(dir);
        }
    }

    public void makeDirectory(String dir)  throws IOException {
        ftpClient.makeDirectory(dir);
    }
    /**
     * FTP删除文件
     *
     * @param remoteFilePath
     */
    public boolean delFile(String remoteFilePath) {
        try {
            return ftpClient.deleteFile(remoteFilePath);
        } catch (IOException e) {
            throw new RuntimeException( e );
        }
    }

    /**
     * FTP下载
     *
     * @throws Exception
     */
    public void download(String localFilePath, String remoteFilePath) throws Exception {
        OutputStream localOut = new FileOutputStream(localFilePath);
        ftpClient.enterLocalPassiveMode();
        ftpClient.retrieveFile(remoteFilePath, localOut);
        localOut.flush();
        if (localOut != null) {
            localOut.close();
        }
    }

    /**
     * FTP下载
     *
     * @throws Exception
     */
    public void download(OutputStream localOut, String remoteFilePath) throws Exception {
        boolean result = ftpClient.retrieveFile(remoteFilePath, localOut);
        if (!result) {
            throw new RuntimeException("文件下载失败!");
        }
    }

    /**
     *获取当前路径
     * @return
     */
    public String printWorkingDirectory(){
        try {
            return ftpClient.printWorkingDirectory();
        } catch (IOException e) {
            throw new RuntimeException("获取当前路径失败!");
        }
    }

    /**
     * FTP文件移动
     *
     * @param fromPath
     * @param toPath
     * @throws Exception
     */
    public boolean reName(String fromPath, String toPath) throws Exception {
        log.error("文件移动 : fromPath : "+fromPath+" , toPath : "+toPath);
        return ftpClient.rename(fromPath, toPath);
    }

    /**
     * 改变当前目录
     * @param dirPath
     * @return
     * @throws Exception
     */
    public boolean changeDirectory(String dirPath) throws Exception {
        return ftpClient.changeWorkingDirectory(dirPath);
    }

    /**
     * Ftp读取文件
     * @param fileName
     * @return
     * @throws Exception
     */
    public BufferedReader readFtpFile(String fileName) throws Exception {
        log.error("读取文件路径 : "+fileName);
        return new BufferedReader(new InputStreamReader(ftpClient.retrieveFileStream(fileName)));
    }

    /**
     * Ftp读取文件成inputStream
     * @param fileName
     * @return
     * @throws Exception
     */
    public InputStream readFtpFileIS(String fileName) throws Exception {
        log.error("读取文件路径 : "+fileName);
        return ftpClient.retrieveFileStream(fileName);
    }

    /**
     * 保存文件到服务器
     * @param remoteFileName
     * @param in
     * @throws Exception
     */
    public void storeFile(String remoteFileName,InputStream in) throws Exception {
        log.info("保存文件名 : "+remoteFileName);
        ftpClient.storeFile(remoteFileName, in);
    }


    /**
     * 获取文件大小
     * @param filePath 文件全路径
     * @throws Exception
     */
    public String getFileSize(String filePath) throws Exception {
        FTPFile[] ftpFiles = ftpClient.listFiles(filePath);
        try {
            if (ftpFiles.length == 1) {
                Long fileSize = ftpFiles[0].getSize();
                return fileSize.toString();
            }else {
                return "0";
            }
        }catch (Exception e){
            return "0";
        }
    }
}
